module calculator
(
    input         clock,
    input         reset,
    input         enter,
    input         add,
    input         multiply,
    input  [ 7:0] data,
    output [15:0] result,
    output        overflow,
    output [ 3:0] error
);

    assign error = 0;

    reg  [15:0] alu_a;
    reg  [15:0] alu_b;
    reg         alu_multiply;
    wire [15:0] alu_result;
    wire        alu_overflow;

    alu alu
    (
        .a          ( alu_a        ),
        .b          ( alu_b        ),
        .multiply   ( alu_multiply ),
        .result     ( alu_result   ),
        .overflow   ( alu_overflow )
    );

    reg r_overflow;
    assign overflow = r_overflow;

    always @(posedge clock)
    begin
        if (reset)
            r_overflow <= 0;
        else
            r_overflow <= alu_overflow;
    end

    reg         stack_push;
    reg         stack_pop;
    reg  [15:0] stack_write_data;
    wire [15:0] stack_read_data;

    stack stack
    (
        .clock      ( clock            ),
        .reset      ( reset            ),
        .push       ( stack_push       ),
        .pop        ( stack_pop        ),
        .write_data ( stack_write_data ),
        .read_data  ( stack_read_data  ) 
    );

    assign result = stack_read_data;

    reg  [15:0] r_alu_a;
    reg  [15:0] r_alu_b;
    reg         r_alu_multiply;
    reg  [ 1:0] state;

    reg  [ 1:0] next_state;

    always @(*)
    begin
        alu_a            = r_alu_a;
        alu_b            = r_alu_b;
        alu_multiply     = r_alu_multiply;
        stack_push       = 0;
        stack_pop        = 0;
        stack_write_data = data;
        next_state       = state;

        case (state)
        0:
           if (enter)
           begin
               stack_push       = 1;
               stack_write_data = data;
           end
           else if (add | multiply)
           begin
               alu_a            = stack_read_data;
               alu_multiply     = multiply;

               stack_pop        = 1;
               next_state       = 1;
           end

        1:
           begin
               alu_b            = stack_read_data;
               stack_pop        = 1;
               next_state       = 2;
           end

        2:
           begin
               stack_push       = 1;
               stack_write_data = alu_result;
               next_state       = 0;
           end

        endcase
    end

    always @(posedge clock)
    begin
        if (reset)
        begin
            r_alu_a        <= 0;
            r_alu_b        <= 0;
            r_alu_multiply <= 0;
            state          <= 0;
        end
        else
        begin
            r_alu_a        <= alu_a;
            r_alu_b        <= alu_b;
            r_alu_multiply <= alu_multiply;
            state          <= next_state;
        end
    end

endmodule
